package de.upb.aquarium.water.bubbles;

import javax.media.opengl.GL;

import de.upb.aquarium.World;
import de.upb.aquarium.api.objects.General3DObject;
import de.upb.aquarium.api.utility.VectorFloat;

public class WaterBubble extends General3DObject {

	private static int displayList = -1;

	static {
		GL gl = World.getInstance().getGL();
		
		displayList = gl.glGenLists(1);
		
		gl.glNewList(displayList, GL.GL_COMPILE);
			gl.glBegin(GL.GL_QUADS);
	        gl.glTexCoord2f(0.0f, 0.0f);
	        gl.glVertex3f(-0.01f, -0.01f, 0.01f);
	        gl.glTexCoord2f(1.0f, 0.0f);
	        gl.glVertex3f(0.01f, -0.01f, 0.01f);
	        gl.glTexCoord2f(1.0f, 1.0f);
	        gl.glVertex3f(0.01f, 0.01f, 0.01f);
	        gl.glTexCoord2f(0.0f, 1.0f);
	        gl.glVertex3f(-0.01f, 0.01f, 0.01f);
	        gl.glEnd();
		gl.glEndList();
	}
	
	private double maxSpeed;
	
	private VectorFloat upDirection;
	private VectorFloat movementDirection;
	
	private double lastUpdateTime;
	
	public WaterBubble(
			double maxSpeed,
			VectorFloat initialPosition,
			VectorFloat upDirection,
			VectorFloat movementDirection) {
		super();
		this.maxSpeed = maxSpeed;
		this.upDirection = upDirection;
		this.movementDirection = movementDirection;
		
		assert(initialPosition.getSize() == 3);
		setPosition(initialPosition.data);
		
		lastUpdateTime = World.getInstance().getGlobalTime();
	}

	public void updatePosition()
	{
		double elapsedTime = World.getInstance().getElapsedTime(lastUpdateTime);
		lastUpdateTime = World.getInstance().getGlobalTime();
		
		VectorFloat pos = new VectorFloat(getPosition());
		VectorFloat change = movementDirection.mul(elapsedTime);

		movementDirection = movementDirection.add(upDirection.mul(elapsedTime));
		
		float movementSpeed = movementDirection.norm();
		if (movementSpeed > maxSpeed)
		{
			movementDirection = movementDirection.mul(maxSpeed/movementSpeed);
		}
		
		setPosition(pos.add(change).data);
	}
	
	@Override
	public void paint(GL gl) {
		
		beforeRendering(gl);
		gl.glCallList(displayList);
		afterRendering(gl);
	}
	
	@Override
	protected void afterRendering(GL gl) {
		
		super.afterRendering(gl);
	}

	@Override
	protected void beforeRendering(GL gl) {
		super.beforeRendering(gl);
		
		double[] mv = new double[16];
		gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mv, 0);
		
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				mv[4*j + i] = (i == j) ? 1.0 : 0.0;
			}
		}
		
		gl.glLoadMatrixd(mv, 0);
	}

	public VectorFloat getMovementDirection() {
		return movementDirection;
	}

	public void setMovementDirection(VectorFloat movementDirection) {
		this.movementDirection = movementDirection;
	}
}
